import express  from  'express';  
import { PrismaClient } from '@prisma/client'
import jwt from 'jsonwebtoken';  
import path from 'path' 
import { dirname } from "node:path"
import { fileURLToPath } from "node:url"
import 'express-async-errors';
import { validationResult } from 'express-validator'  
import cors from 'cors'
import _expressWs  from 'express-ws'
import NodeCache from 'node-cache';                     // 服务端的本地缓存类库
const _cache = new NodeCache();
const ClintMap = new Map();

// controller 路由
import UserRouter from './controller/user.js'
import commonRouter from './controller/common.js'
import OrderRouter from './controller/order.js'
import DriverRouter from './controller/driver.js'
import BrandRouter from './controller/brand.js'

// socket的控制器
import { 
  handleOrderBrocast,
  handleAappceptOrder,
  handleUpdateDriverLoc,
 } from './wscontroller/index.js'
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const app = express();  
app.use(cors())
const expressWs = _expressWs(app)
const PORT = 3000;  
const prisma = new PrismaClient()

// 设置静态文件目录  
app.use(express.static(path.join(__dirname, 'public')));  
app.use(express.json())
app.use(express.urlencoded({extended:false}))

const secretKey = 'qfdixon'; // 替换为你的密钥  

const initBrand = async (req)=>{
  const count = await req.prisma.brand.count();
  if(count === 0){
    try{
      await req.prisma.Brand.createMany({
        data:[
       
          { 
            name:'问界m5',
            lv:3,
            pid:0
          },
          { 
            name:'问界m7',
            lv:3,
            pid:0
          },
          {
            name: '传祺gs4',
            lv: 3,
            pid:0
          }
        ]
      })
    } catch (e) {
      console.log('e', e)
    }

  } 
}

// 一些自己配置的中间件
app.use((req,res,next)=>{
    // 使用Prisma
    req.prisma = prisma
    res.success = (data)=>{
        res.json({
            success: true,
            data
        })
    }
    res.fail = (error)=>{
        res.status(200).json({
            success: false,
            info: error
        }).end()
    }
    
    // 缓存cache
    req.nodeCache = _cache;

    // 执行类型检测
    res.validator = ()=>{
        const error = validationResult(req).array({ onlyFirstError: true });
        if(error.length)  {
           res.fail(error[0].msg) 
           res.end();
        }
    }

    
    req.toAll =(msg)=>{
      const clients = [...expressWs.getWss().clients]
      for(const cl of clients){
        cl.send(msg)
      }
    }
    req.toOne = (who,msg)=>{
      const ws = ClintMap.get(who);
      if(ws){
        ws.send(msg)
      }
    }

    req.ClintMap = ClintMap;

    // 处理初始化的品牌
    initBrand(req)

    next()
})
  
// 生成JWT令牌  
function generateToken(user) {  
  const secretKey = 'qfdixon'; // 替换为你的密钥  
  return jwt.sign({ user }, secretKey, { expiresIn: '24h' });  
}  
  
// 验证JWT令牌  
function verifyToken(req, res, next) {  
  const token = req.headers['authorization'];  
  console.log('token', token)
  if (!token) return res.sendStatus(401);  
  jwt.verify(token, secretKey, {
    maxAge: '1d'
  }, (err, user) => {  
    console.log('err',err)
    if (err) return res.sendStatus(403);  
    console.log('用户信息是',user);
    req.user = user;  
    next();  
  });  
}  

// 用于测试的借口
app.post('/test', (req, res) => {  
    res.success({
      info:'测试成功',
      data: req.body
    })
});  

// 登录接口  
app.post('/login', (req, res) => {  
  const { username, password } = req.body;  
  // 在这里进行用户名和密码的验证，返回用户信息或错误信息  
  // 这里只是一个示例，你需要根据实际情况进行验证  
  if (username === 'admin' && password === 'password') {  
    const token = generateToken({ username });  
    res.json({ token });  
  } else {  
    res.sendStatus(401);  
  }  
});  
  
app.use('/user', UserRouter);
app.use('/order',verifyToken, OrderRouter);
app.use('/driver', DriverRouter);
app.use('/brand', BrandRouter);


app.use(commonRouter);


// 全局捕获错误
const errorHandling = (err, req, res, next) => {
  console.log('err',err)
    res.status(500).json({
      msg: err.message,
      success: false,
    });

}
 app.use(errorHandling);


 // socket 流程




 app.ws('/ws', function(ws, req) {
  const { phone, type, } = req.query;
  ClintMap.set(`${phone}_${type}`, ws);
  
  
  ws.on('message', function(msg) {
    const postData = JSON.parse(msg);

    const { type ,payload} = postData;
    if(type!='ping' && type!='updateDriveLocation')     console.log('socket info ', postData)
    if(type === 'test'){
      ws.send(JSON.stringify({type:'abc',payload:'服务端的随机数据'}))
    }
    if(type == 'addOrder' ){
      handleOrderBrocast(payload,req)
    }
    if(type == 'acceptOrder'){
      handleAappceptOrder(payload,req)
    }
    if(type == 'updateDriveLocation'){
      handleUpdateDriverLoc(payload,req)
    }
  });

  // 链接成功之后给所有的建立链接的socket客户端
  req.toAll(JSON.stringify({type:'test',payload:123}))

});
  
// 启动应用程序  
app.listen(PORT, () => {  
  console.log(`Server is running on port ${PORT}`);  
});